package com.xxd.dfs.backupnode;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author: XiaoDong.Xie
 * @create: 2020-08-14 09:16
 * @description: 负责文件目录维护
 */
public class FSDirectory {

    private final Logger logger = LoggerFactory.getLogger(FSDirectory.class);

    /**
     * 根目录
     */
    INode dirTree = new INode("/");

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void writeLock() {
        lock.writeLock().lock();
    }

    public void readLock() {
        lock.readLock().lock();
    }

    public void writeUnLock() {
        lock.writeLock().unlock();
    }

    public void readUnLock() {
        lock.readLock().unlock();
    }


    /**
     * 在原文件目录基础上，创建一个新的path
     *
     * @param path
     * @return
     */
    public void mkdir(String path) {
        try {
            writeLock();
            INode parent = dirTree;

            String[] pathSplited = splitePath(path);
            for (String curPath : pathSplited) {
                INode dir = findDirector(parent, curPath);

                if (dir != null) {
                    parent = dir;
                    continue;
                }

                // 没有找到 就需要创建这个目录
                INode curNode = new INode(curPath);
                parent.children.add(curNode);
                // 找到了，那么需要
                parent = curNode;
            }

        } finally {
            writeUnLock();
        }
    }

    public void setRootDir(INode root) {
        this.dirTree = root;
    }

    public void printlnTree() {
        printlnTree(dirTree, "");
    }

    public void printlnTree(INode dirTree, String blank) {
        System.out.println(blank + dirTree.path);
        for (INode child : dirTree.children) {
            printlnTree(child, blank + "   ");
        }
    }

    /**
     * 判断当前Node 是否有curPath路劲呢
     *
     * @param parentNode
     * @param curPath
     * @return
     */
    private INode findDirector(INode parentNode, String curPath) {
        List<INode> children = parentNode.children;
        if (children != null && !children.isEmpty()) {
            for (INode child : children) {
                if (child.path.equals(curPath)) {
                    return child;
                }
            }
        }
        return null;
    }

    /**
     * 切割路劲
     *
     * @param path
     * @return
     */
    private String[] splitePath(String path) {
        String[] paths = path.split("/");
        String[] dests = new String[paths.length - 1];
        System.arraycopy(paths, 1, dests, 0, paths.length - 1);
        return dests;
    }

    /**
     * 以json格式获取到fsimage内存元数据
     *
     * @return
     */
    public String getFSImageJSON() {
        try {
            readLock();
            String fsimageJson = JSONObject.toJSONString(dirTree);
            return fsimageJson;
        } finally {
            readUnLock();
        }
    }

    static class INode {
        /**
         * 当前的路劲名称
         */
        String path;

        /**
         * 孩子目录
         */
        List<INode> children = new ArrayList<>();

        public INode(String path) {
            this.path = path;
        }

        public INode() {
        }

        public String getPath() {
            return path;
        }

        public void setPath(String path) {
            this.path = path;
        }

        public List<INode> getChildren() {
            return children;
        }

        public void setChildren(List<INode> children) {
            this.children = children;
        }

        @Override
        public String toString() {
            return "INode{" +
                    "path='" + path + '\'' +
                    ", children=" + children +
                    '}';
        }
    }
}
